﻿using System;
using System.Collections.Generic;
using System.Configuration;
using System.Linq;
using System.Net;
using System.Net.Configuration;
using System.Net.Mail;
using System.Security.Cryptography;
using System.Text;
using System.Text.RegularExpressions;
using System.Web;
using CSS.Action;
using CSS.Common;
using Thuoc24h.Data;
using Thuoc24h.Common.Enums;

namespace Thuoc24h.Common
{
    public static class Utils
    {
        public static string ToSeoName(this object strInput, string seoPattern = "-")
        {
            var strOutput = WebUtility.HtmlDecode(strInput.ToString().Trim()).ToNonUnicode().Replace(" ", seoPattern).Replace("----", "-").Replace("---", "-").Replace("--", "-").Replace("\"", "").Replace("?", "").Replace("&", "").Replace("'", "").Replace(":", "").Replace("+", "");
            return strOutput;
        }

        public static string ToNonUnicode(this object strInput)
        {
            var strOutput = strInput.ToString().Trim();
            const string originalText = "áàảãạâấầẩẫậăắằẳẵặđéèẻẽẹêếềểễệíìỉĩịóòỏõọôốồổỗộơớờởỡợúùủũụưứừửữựýỳỷỹỵÁÀẢÃẠÂẤẦẨẪẬĂẮẰẲẴẶĐÉÈẺẼẸÊẾỀỂỄỆÍÌỈĨỊÓÒỎÕỌÔỐỒỔỖỘƠỚỜỞỠỢÚÙỦŨỤƯỨỪỬỮỰÝỲỶỸỴ";
            const string replacedText = "aaaaaaaaaaaaaaaaadeeeeeeeeeeeiiiiiooooooooooooooooouuuuuuuuuuuyyyyyAAAAAAAAAAAAAAAAADEEEEEEEEEEEIIIIIOOOOOOOOOOOOOOOOOUUUUUUUUUUUYYYYY";
            var index = -1;
            while ((index = strOutput.IndexOfAny(originalText.ToCharArray())) != -1)
            {
                var index2 = originalText.IndexOf(strOutput[index]);
                strOutput = strOutput.Replace(strOutput[index], replacedText[index2]);
            }
            return strOutput;
        }

        public static string GetLeft(this object _str, int lenght, bool flag)
        {
            const int index = 0;
            string output;
            var str = _str.ToString();
            try
            {
                if (str.Length >= lenght)
                {
                    output = str.Substring(index, lenght) + "...";
                    if (flag)
                    {
                        var lastIndex = output.LastIndexOf(" ", StringComparison.Ordinal);
                        output = output.Substring(index, lastIndex) + "...";
                    }
                }
                else
                {
                    return str;
                }
            }
            catch (Exception)
            {
                return string.Empty;
            }

            return output;
        }

        public static string GetPINCode()
        {
            Random rnd = new Random();
            int r = rnd.Next(0, 10000);
            return r.ToString("0000#");

            //return RandomText.Generate();
        }

        public static Int32 ToInt32Return0<T>(this T input)
        {
            int output = 0;
            if (null != input)
            {
                try
                {
                    output = Convert.ToInt32(input);
                }
                catch (Exception)
                {
                    return output;
                }
            }

            return output;
        }

        public static Decimal ToDecimalReturn0<T>(this T input)
        {
            decimal output = 0m;
            if (null != input)
            {
                try
                {
                    output = Convert.ToDecimal(input);
                }
                catch (Exception)
                {
                    return output;
                }
            }

            return output;
        }


        //public static Int32 ParseInt32Return0<T>(this T input)
        //{
        //    int output = 0;
        //    if (null != input)
        //    {
        //        try
        //        {
        //            output = Int32.Parse(input.ToString());

        //        }
        //        catch (Exception)
        //        {
        //            return output;
        //        }
        //    }

        //    return output;

        //}
        public static Int64 ToInt64Return0<T>(this T input)
        {
            Int64 output = 0;
            if (null != input)
            {
                try
                {
                    output = Convert.ToInt64(input);
                }
                catch (Exception)
                {
                    return output;
                }
            }

            return output;
        }

        public static Double ToDoubleReturn0<T>(this T input)
        {
            Double output = 0;
            if (null != input)
            {
                try
                {
                    output = Convert.ToDouble(input);
                }
                catch (Exception)
                {
                    return output;
                }
            }

            return output;
        }

        public static bool CheckSubcode(string subcode)
        {
            //if (Nulls.IsNullOrEmpty(subcode)) return false;
            if (subcode.Length > 30) return false;
            if (subcode.ToLower().Contains("=")) return false;
            if (subcode.ToLower().Contains("&")) return false;
            if (subcode.ToLower().Contains("'")) return false;
            if (subcode.ToLower().Contains("\"")) return false;

            return true;
        }

        public static void Redirect(string strFormNames, string Id)
        {
            string strRedirect = strFormNames + "?" + ParameterName.ID + "=" + Id;
            HttpContext.Current.Response.Redirect(strRedirect);
        }

        public static void Redirect(string strFormNames)
        {
            string strRedirect = strFormNames;
            HttpContext.Current.Response.Redirect(strRedirect);
        }

        public static void GoBackToView()
        {
        }

        public static bool IsNotNull<T>(this T input)
        {
            bool output = null != input;
            return output;
        }

        public static bool IsEmailAddress(this string s)
        {
            Regex regex = new Regex(@"^[\w-\.]+@([\w-]+\.)+[\w-]{2,4}$");
            return regex.IsMatch(s);
        }

        public static bool IsNullOrEmpty<T>(this List<T> list)
        {
            return list == null || list.Count == 0;
        }

        public static long FileSize(this string filePath)
        {
            long bytes = 0;

            try
            {
                System.IO.FileInfo oFileInfo = new System.IO.FileInfo(filePath);
                bytes = oFileInfo.Length;
            }
            catch { }
            return bytes;
        }

        public static string EncryptParam(string content, string key)
        {
            key += "@13^36&*70%($)foto@";
            var toEncryptArray = Encoding.UTF8.GetBytes(content);
            var hashmd5 = new MD5CryptoServiceProvider();
            var keyArray = hashmd5.ComputeHash(Encoding.UTF8.GetBytes(key));
            var tdes = new TripleDESCryptoServiceProvider { Key = keyArray, Mode = CipherMode.ECB, Padding = PaddingMode.PKCS7 };
            var cTransform = tdes.CreateEncryptor();
            var resultArray = cTransform.TransformFinalBlock(toEncryptArray, 0, toEncryptArray.Length);
            return Convert.ToBase64String(resultArray, 0, resultArray.Length);
        }
        /// <summary>
        /// giai ma chuoi ky tu da duoc ma hoa
        /// </summary>
        /// <param name="key">tu khoa de giai ma can phai trung voi tu khoa khi tao ma hoa</param>
        /// <param name="content"></param>
        /// <returns></returns>
        public static string DecryptParam(string content, string key)
        {
            key += "@13^36&*70%($)foto@";
            var toEncryptArray = Convert.FromBase64String(content);
            var hashmd5 = new MD5CryptoServiceProvider();
            var keyArray = hashmd5.ComputeHash(Encoding.UTF8.GetBytes(key));
            var tdes = new TripleDESCryptoServiceProvider { Key = keyArray, Mode = CipherMode.ECB, Padding = PaddingMode.PKCS7 };
            var cTransform = tdes.CreateDecryptor();
            var resultArray = cTransform.TransformFinalBlock(
            toEncryptArray, 0, toEncryptArray.Length);
            return Encoding.UTF8.GetString(resultArray);
        }


        public static string Encrypt(this string stringToEncrypt)
        {
            MD5 md = new MD5CryptoServiceProvider();
            byte[] bytes = Encoding.Default.GetBytes(stringToEncrypt);
            return BitConverter.ToString(md.ComputeHash(bytes));
        }

        public static string Decrypt(this string stringToDecrypt, string key)
        {
            string result;

            if (string.IsNullOrEmpty(stringToDecrypt))
            {
                throw new ArgumentException("An empty string value cannot be encrypted.");
            }

            if (string.IsNullOrEmpty(key))
            {
                throw new ArgumentException("Cannot decrypt using an empty key. Please supply a decryption key.");
            }

            try
            {
                CspParameters cspp = new CspParameters();
                cspp.KeyContainerName = key;

                RSACryptoServiceProvider rsa = new RSACryptoServiceProvider(cspp);
                rsa.PersistKeyInCsp = true;

                string[] decryptArray = stringToDecrypt.Split(new[] { "-" }, StringSplitOptions.None);
                byte[] decryptByteArray = Array.ConvertAll(decryptArray, (s => Convert.ToByte(byte.Parse(s, System.Globalization.NumberStyles.HexNumber))));

                byte[] bytes = rsa.Decrypt(decryptByteArray, true);

                result = System.Text.Encoding.UTF8.GetString(bytes);
            }
            finally
            {
                // no need for further processing
            }

            return result;
        }

        #region DateTime

        public static DateTime GetFirstDayOfWeek()
        {
            return DateTime.Now.AddDays(1 - (int)DateTime.Now.DayOfWeek);
        }

        public static DateTime GetFirstDayOfMonth()
        {
            return DateTime.Now.AddDays(1 - DateTime.Now.Day);
        }

        public static DateTime GetFirstDayOfQuarter()
        {
            DateTime time = DateTime.Now;
            while (time.Month % 3 != 1) time = time.AddMonths(-1);
            return time.AddDays(1 - time.Day);
        }

        public static DateTime GetFirstDayOfYear()
        {
            return DateTime.Now.AddDays(1 - DateTime.Now.DayOfYear);
        }

        public static DateTime GetLastDayOfWeek()
        {
            return DateTime.Now.AddDays(7 - (int)DateTime.Now.DayOfWeek);
        }

        public static DateTime GetLastDayOfMonth()
        {
            DateTime time = DateTime.Now.AddMonths(1);
            return time.AddDays(0 - time.Day);
        }

        public static DateTime GetLastDayOfQuarter()
        {
            DateTime time = DateTime.Now;
            while (time.Month % 3 != 0) time = time.AddMonths(1);
            time = time.AddMonths(1);
            return time.AddDays(0 - time.Day);
        }

        public static DateTime GetLastDayOfYear()
        {
            DateTime time = DateTime.Now.AddYears(1);
            return time.AddDays(0 - time.DayOfYear);
        }

        #endregion

        public static bool SendMailMessage(string to, string subject, string body, string attachFileUrl)
        {
            bool sendStatus = false;
            try
            {
                if (!string.IsNullOrEmpty(to))
                {
                    var sec = (SmtpSection)ConfigurationManager.GetSection("system.net/mailSettings/smtp");
                    var mail = new MailMessage();
                    mail.To.Add(to);
                    mail.From = new MailAddress(sec.From);
                    mail.Subject = subject;
                    mail.Body = body;
                    mail.IsBodyHtml = true;
                    mail.BodyEncoding = Encoding.UTF8;
                    mail.ReplyTo = new MailAddress(sec.From);
                    if (!string.IsNullOrEmpty(attachFileUrl))
                    {
                        mail.Attachments.Add(new Attachment(attachFileUrl));
                    }
                    SmtpClient smtp = new SmtpClient();
                    smtp.UseDefaultCredentials = false;
                    smtp.DeliveryMethod = SmtpDeliveryMethod.Network;
                    smtp.Host = sec.Network.Host;
                    smtp.Port = sec.Network.Port;

                    smtp.EnableSsl = true;
                    smtp.Credentials =
                        new System.Net.NetworkCredential(sec.Network.UserName, sec.Network.Password);
                    smtp.Timeout = 3600000;
                    smtp.Send(mail);
                    sendStatus = true;
                }

            }
            catch (Exception ex)
            {
                throw new Exception(ex.Message);
            }
            return sendStatus;
        }


        public static string RemoveUnicode(string text)
        {
            string[] arr1 = new string[] { "á", "à", "ả", "ã", "ạ", "â", "ấ", "ầ", "ẩ", "ẫ", "ậ", "ă", "ắ", "ằ", "ẳ", "ẵ", "ặ",  
        "đ",  
        "é","è","ẻ","ẽ","ẹ","ê","ế","ề","ể","ễ","ệ",  
        "í","ì","ỉ","ĩ","ị",  
        "ó","ò","ỏ","õ","ọ","ô","ố","ồ","ổ","ỗ","ộ","ơ","ớ","ờ","ở","ỡ","ợ",  
        "ú","ù","ủ","ũ","ụ","ư","ứ","ừ","ử","ữ","ự",  
        "ý","ỳ","ỷ","ỹ","ỵ",};
            string[] arr2 = new string[] { "a", "a", "a", "a", "a", "a", "a", "a", "a", "a", "a", "a", "a", "a", "a", "a", "a",  
        "d",  
        "e","e","e","e","e","e","e","e","e","e","e",  
        "i","i","i","i","i",  
        "o","o","o","o","o","o","o","o","o","o","o","o","o","o","o","o","o",  
        "u","u","u","u","u","u","u","u","u","u","u",  
        "y","y","y","y","y",};
            for (int i = 0; i < arr1.Length; i++)
            {
                text = text.Replace(arr1[i], arr2[i]);
                text = text.Replace(arr1[i].ToUpper(), arr2[i].ToUpper());
            }
            return text;
        }
        public static string ToUnsignName(string text)
        {
            text = CSS.Utils.RemoveUnicode(text);
            text = CSS.Utils.ToSeoFriendly(text, 200);
            return text;
        }
        public static string ToSeoFriendly(string title, int maxLength)
        {
            var match = Regex.Match(title.ToLower(), "[\\w]+");
            StringBuilder result = new StringBuilder("");
            bool maxLengthHit = false;
            while (match.Success && !maxLengthHit)
            {
                if (result.Length + match.Value.Length <= maxLength)
                {
                    result.Append(match.Value + "-");
                }
                else
                {
                    maxLengthHit = true;
                    if (result.Length == 0) result.Append(match.Value.Substring(0, maxLength));
                }
                match = match.NextMatch();
            }
            if (result[result.Length - 1] == '-') result.Remove(result.Length - 1, 1);
            return result.ToString();
        }
        public static string BuildSeoLink(object unsignUrl)
        {
            return unsignUrl.ToString().ToLower() + AppSettings.GetString(Constants.URL_EXTENTION);
        }
        public static string BuildUrl(object name, object id = null)
        {
            if (id == null)
            {
                return BuildSeoLink(ToUnsignName(name.ToString()));
            }
            else
            {
                return BuildSeoLink(ToUnsignName(name.ToString()) + "-" + id);
            }
        }
        public static string BuildVoteMark(object total = null, object voteCount = null)
        {
            string html = "<div class=\"VoteItem\"><div class=\"VoteValue\" style=\"width:{0}%\"></div></div>";
            if (total == null || voteCount == null)
            {
                html = string.Format(html, 100);
            }
            else
            {
                double _total = int.Parse(total.ToString());
                double _count = int.Parse(voteCount.ToString());
                if (_total == 0)
                {
                    _total = 5;
                }
                if (_count == 0)
                {
                    _count = 1;
                }
                var percent = ((_total / _count) / 5) * 100;
                html = string.Format(html, percent);
            }
            return html;
        }
        public static string GetYoutubeVideoThumb(object videoUrl)
        {
            Regex reg = new Regex(@"youtu(?:\.be|be\.com)/(?:.*v(?:/|=)|(?:.*/)?)([a-zA-Z0-9-_]+)");
            Match youtubeMatch = reg.Match(videoUrl + "");
            string id = string.Empty;
            if (youtubeMatch.Success)
                id = youtubeMatch.Groups[1].Value;
            return string.Format("http://img.youtube.com/vi/{0}/mqdefault.jpg", id);
        }
        public static string GetOsIconUrl(object osName)
        {
            return "/Home/theme/images/" + ToSeoFriendly(RemoveUnicode(osName.ToString()), 100) + ".png";
        }
        public static string GetConfig(string key)
        {
            MedLifeDataContext ct = new MedLifeDataContext();
            var config = ct.Configs.FirstOrDefault(it => it.Name.ToLower() == key.ToLower());
            if (config != null)
            {
                return config.Data;
            }
            else
            {
                return "";
            }
        }
        public static string FormatMoney(object moneyString)
        {
            if (moneyString != null)
            {
                return Double.Parse(moneyString.ToString()).ToString("#,###").Replace(",", ".") + " đ";
            }
            else
            {
                return "0";
            }
        }
        public static T GetEnumObjectByValue<T>(int? valueId)
        {
            try
            {
                return (T)Enum.ToObject(typeof(T), valueId);
            }
            catch (Exception ex)
            {
                return (T)Enum.ToObject(typeof(Unit), 1);
            }
        }
    }
}